﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading.Tasks;
using CivilisationLib;

namespace IHM
{
    /// <summary>
    /// Logique d'interaction pour CartieIHM.xaml
    /// </summary>
    public partial class CarteIHM : Window
    {
        Partie partie;
        Carte carte;
        Rectangle[,] cases;
        List<Ellipse> unites;
        List<Rectangle> villes;
        List<Rectangle> exploitations;
        List<Ellipse> deplacements;
        //List<Rectangle> villesPotentielles;

        Point? lastCenterPositionOnTarget;
        Point? lastMousePositionOnTarget;
        Point? lastDragPoint;
        
        /// <summary>
        /// Initialise la fenetre CarteIHM
        /// </summary>
        /// <param name="p"></param>
        public CarteIHM(Partie p)
        {
            partie = p;
            carte = partie.carte;
            InitializeComponent();
            initialisation();
            KeyDown += new KeyEventHandler(actionsClavier);
            this.MouseLeftButtonDown += new MouseButtonEventHandler(Window_MouseLeftButtonDown);

            scroll.ScrollChanged += OnScrollViewerScrollChanged;
            scroll.MouseLeftButtonUp += OnMouseLeftButtonUp;
            scroll.PreviewMouseLeftButtonUp += OnMouseLeftButtonUp;
            scroll.PreviewMouseWheel += OnPreviewMouseWheel;
            survolCase.PreviewMouseLeftButtonDown += OnMouseLeftButtonDown;
            scroll.MouseMove += OnMouseMove;
            slider.ValueChanged += OnSliderValueChanged;
        }


        /// <summary>
        /// Méthode indiquant les actions à effectuer lors du déplacement de la souris si l'utilisateur effectue un drag de la carte.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnMouseMove(object sender, MouseEventArgs e)
    {
        if (lastDragPoint.HasValue)
        {
            Point posNow = e.GetPosition(scroll);

            double dX = posNow.X - lastDragPoint.Value.X;
            double dY = posNow.Y - lastDragPoint.Value.Y;

            lastDragPoint = posNow;

            scroll.ScrollToHorizontalOffset(scroll.HorizontalOffset - dX);
            scroll.ScrollToVerticalOffset(scroll.VerticalOffset - dY);
        }
    }

        /// <summary>
        /// Méthode indiquant les actions à effectuer lors d'un clique sur la carte : Pose le drag
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var mousePos = e.GetPosition(scroll);
            if (mousePos.X <= scroll.ViewportWidth && mousePos.Y < scroll.ViewportHeight)
            {
                scroll.Cursor = Cursors.SizeAll;
                lastDragPoint = mousePos;
                Mouse.Capture(scroll);
            }
            selectionVide(sender, e);
        }

        /// <summary>
        /// Méthode indiquant les actions à effectuer lors de l'utilisation de la molette sur la carte
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            lastMousePositionOnTarget = Mouse.GetPosition(mapGrid);

            if (e.Delta > 0)
            {
                slider.Value += 0.5;
            }
            if (e.Delta < 0)
            {
                slider.Value -= 0.5;
            }

            e.Handled = true;
        }

        /// <summary>
        /// Méthode indiquant les actions à effectuer du relachement de la souris : libere le drag
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            scroll.Cursor = Cursors.Arrow;
            scroll.ReleaseMouseCapture();
            lastDragPoint = null;
        }


        /// <summary>
        /// Méthode indiquant les actions à effectuer lorsque la valeur du slider pour le zoom change.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnSliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            scaleTransform.ScaleX = e.NewValue;
            scaleTransform.ScaleY = e.NewValue;

            var centerOfViewport = new Point(scroll.ViewportWidth / 2,
                                             scroll.ViewportHeight / 2);
            lastCenterPositionOnTarget = scroll.TranslatePoint(centerOfViewport, mapGrid);
        }

        /// <summary>
        /// Méthode indiquant les actions à effectuer lorsque l'offset du scrollviewer change.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnScrollViewerScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            if (e.ExtentHeightChange != 0 || e.ExtentWidthChange != 0)
            {
                Point? targetBefore = null;
                Point? targetNow = null;

                if (!lastMousePositionOnTarget.HasValue)
                {
                    if (lastCenterPositionOnTarget.HasValue)
                    {
                        var centerOfViewport = new Point(scroll.ViewportWidth / 2,
                                                         scroll.ViewportHeight / 2);
                        Point centerOfTargetNow =
                              scroll.TranslatePoint(centerOfViewport, mapGrid);

                        targetBefore = lastCenterPositionOnTarget;
                        targetNow = centerOfTargetNow;
                    }
                }
                else
                {
                    targetBefore = lastMousePositionOnTarget;
                    targetNow = Mouse.GetPosition(mapGrid);

                    lastMousePositionOnTarget = null;
                }

                if (targetBefore.HasValue)
                {
                    double dXInTargetPixels = targetNow.Value.X - targetBefore.Value.X;
                    double dYInTargetPixels = targetNow.Value.Y - targetBefore.Value.Y;

                    double multiplicatorX = e.ExtentWidth / mapGrid.Width;
                    double multiplicatorY = e.ExtentHeight / mapGrid.Height;

                    double newOffsetX = scroll.HorizontalOffset -
                                        dXInTargetPixels * multiplicatorX;
                    double newOffsetY = scroll.VerticalOffset -
                                        dYInTargetPixels * multiplicatorY;

                    if (double.IsNaN(newOffsetX) || double.IsNaN(newOffsetY))
                    {
                        return;
                    }

                    scroll.ScrollToHorizontalOffset(newOffsetX);
                    scroll.ScrollToVerticalOffset(newOffsetY);
                }
            }
        }


        /// <summary>
        /// Méthode gérant l'ensemble des actions s'executant après l'appui d'une touche sur le clavier.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void actionsClavier(object sender, KeyEventArgs e)
        {
            //if (e.Key == Key.Space && e.IsDown) afficherVillesPotentielles();
            //if (e.Key == Key.Space && e.IsUp) masquerVillesPotentielles();

            if (e.Key == Key.Enter) tourSuivant();
            if (selectionUnite.IsVisible)
            {
                deplacerUnite(e, (Unite)listUnites.SelectedValue);
                boutonFonderVille();
            }
            e.Handled = true;
        }
        
        
        /*
        private void masquerVillesPotentielles()
        {
            foreach (Rectangle r in villesPotentielles)
            {
                mapGrid.Children.Remove(r);
            }
        }
        
        private void afficherVillesPotentielles()
        {
            Position[] villesPot = carte.potentiellesVilles();
            foreach (Position p in villesPot)
            {
                var r = new Rectangle();
                r.Height = 30;
                r.Width = 30;
                r.Fill = Brushes.White;
                r.Stroke = Brushes.Gray;
                r.StrokeThickness = 1.5;
                Grid.SetColumn(r, p.X);
                Grid.SetRow(r, p.Y);
                Grid.SetZIndex(r, 330);
                villesPotentielles.Add(r);
                mapGrid.Children.Add(r);
            }
        }
        */
        
        /// <summary>
        /// Méthodes supplémentaires nécessaires à l'initialisation de la fenetre.
        /// </summary>
        public void initialisation()
        {
            partie.commencerPartie();
            exploitations = new List<Rectangle>();
            deplacements = new List<Ellipse>();
            creerEllipsesUnites();
            creerRectanglesVilles();
            creerRectanglesExploitations();
            afficherShapes();
            _root.Tag = partie.tour;
        }

        /// <summary>
        /// Permet le deplacement d'une unite par le clavier
        /// </summary>
        /// <param name="e"></param>
        /// <param name="u"></param>
        private void deplacerUnite(KeyEventArgs e, Unite u)
        {
            bool dep = false;
            if (e.Key == Key.Down)
            {
                dep = u.deplacer(Unite.Directions.DOWN);
            }
            if (e.Key == Key.Up)
            {
                dep = u.deplacer(Unite.Directions.UP);
            }
            if (e.Key == Key.Right)
            {
                dep = u.deplacer(Unite.Directions.RIGHT);
            }
            if (e.Key == Key.Left)
            {
                dep = u.deplacer(Unite.Directions.LEFT);
            }


            if (u.vie == 0) selectionUnite.Visibility = System.Windows.Visibility.Collapsed;
            survolUnite.Visibility = System.Windows.Visibility.Collapsed;
            mvt.GetBindingExpression(Label.ContentProperty).UpdateTarget();
            vie.GetBindingExpression(Label.ContentProperty).UpdateTarget();
            majSelectionUnite(u);
            majEllipsesDeplacements();
            majBrouillard();
            finDePartie();
            majShapes();
        }

        /// <summary>
        /// Vérifie la défaite des joueurs, et annonce l'éventuelle victoire
        /// </summary>
        private void finDePartie()
        {
            Joueur looser = new Joueur();
            foreach (Joueur j in partie.joueurs)
            {
                if (j.perdu)
                {
                    looser = j;
                }
            }

            if (looser.civilisation != null)
            {
                perdant.Content = looser.pseudo;
                partie.detruireJoueur(looser);
                defaite.Visibility = System.Windows.Visibility.Visible;
            }

            if (partie.joueurs.Count == 1)
            {
                vainqueur.Content = partie.joueurs.First().pseudo;
                victoire.Visibility = System.Windows.Visibility.Visible;
            }
        }

        /// <summary>
        /// Met à jour l'ellipse de selection d'unite
        /// </summary>
        /// <param name="u"></param>
        private void majSelectionUnite(Unite u)
        {
            Grid.SetColumn(selectionUnite, u.pos.X);
            Grid.SetRow(selectionUnite, u.pos.Y);
            var lu = carte.getUnites(u.pos);
            selectionUnite.Tag = lu;
            listUnites.SelectedValue = u;
        }

        /// <summary>
        /// Met à jour les shapes representant les unites, les villes et leurs exploitations.
        /// </summary>
        private void majShapes()
        {
            masquerShapes();
            creerEllipsesUnites();
            creerRectanglesVilles();
            creerRectanglesExploitations();
            afficherShapes();
        }

        /// <summary>
        /// Permet le retour au menu principal
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MenuPrincipal(object sender, RoutedEventArgs e)
        {
            MenuPrincipal menu = new MenuPrincipal();
            App.Current.MainWindow = menu;
            this.Close();
            menu.Show();
        }

        /// <summary>
        /// Quitte le jeu
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Quitter(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// Genere la carte
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            cases = new Rectangle[carte.largeur, carte.largeur];
            for (int c = 0; c < carte.largeur; c++)
            {
                mapGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(50, GridUnitType.Pixel) });
            }
            for (int l = 0; l < carte.largeur; l++)
            {
                mapGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(50, GridUnitType.Pixel) });
                for (int c = 0; c < carte.largeur; c++)
                {
                    var tile = carte.getCase(c, l);
                    var element = creerCase(c, l, tile);
                    cases[c, l] = element;
                    mapGrid.Children.Add(element);
                }
            }
            majBrouillard();
        }


        /// <summary>
        /// Cree les ellipses correspondantes aux unites d'un joueur
        /// </summary>
        private void creerEllipsesUnites()
        {
            List<Ellipse> le = new List<Ellipse>(carte.listesUnitesNonVides().Count);
            foreach (List<Unite> lu in carte.listesUnitesNonVides())
            {
                le.Add(creerEllipseUnite(lu));        
            }
            unites = le;
        }

        /// <summary>
        /// Cree les rectangles correspondants aux villes des joueurs.
        /// </summary>
        private void creerRectanglesVilles()
        {
            List<Rectangle> lr = new List<Rectangle>(carte.listeVilles().Count);
            foreach (Ville v in carte.listeVilles())
            {
                lr.Add(creerRectangleVille(v));
            }
            villes = lr;
        }
        /// <summary>
        /// Cree l'ellipse d'une liste d'unite
        /// </summary>
        /// <param name="lu"></param>
        /// <returns></returns>
        private Ellipse creerEllipseUnite(List<Unite> lu)
        {

            var l = new Label();
            l.Content = lu.Count;
            l.Tag = lu;
            l.Style = labelUnite.Style;
            l.MouseEnter+= new MouseEventHandler(unite_MouseEnter);
            Grid.SetColumn(l, lu.First().pos.X);
            Grid.SetRow(l, lu.First().pos.Y);
            Grid.SetZIndex(l, 350);

            var e = new Ellipse();
            e.Height = 25;
            e.Width = 25;
            e.Tag = l;
            e.Fill = ColorToSolidColorBrush(lu.First().civilisation.couleurUnite);
            e.Stroke = Brushes.White;
            e.StrokeThickness = 1.5;

            if (lu.First().estVisible())
            {
                e.Visibility = System.Windows.Visibility.Visible;
                l.Visibility = System.Windows.Visibility.Visible;
            }
            else
            {
                e.Visibility = System.Windows.Visibility.Collapsed;
                l.Visibility = System.Windows.Visibility.Collapsed;
            }


            Grid.SetColumn(e, lu.First().pos.X);
            Grid.SetRow(e, lu.First().pos.Y);
            Grid.SetZIndex(e, 340);

            return e;
        }

        /// <summary>
        /// Cree un rectangle correspondant à une ville
        /// </summary>
        /// <param name="v"></param>
        /// <returns></returns>
        private Rectangle creerRectangleVille(Ville v)
        {
            var l = new Label();
            l.Content = v.population;
            l.Tag = v;
            l.Style = labelVille.Style;
            Grid.SetColumn(l, v.pos.X);
            Grid.SetRow(l, v.pos.Y);
            Grid.SetZIndex(l, 332);

            var r = new Rectangle();
            r.Height = 30;
            r.Width = 30;
            r.Tag = v;
            r.Fill = ColorToSolidColorBrush(v.civilisation.couleurVille);
            r.Stroke = Brushes.White;
            r.StrokeThickness = 1.5;
            r.MouseEnter += new MouseEventHandler(ville_MouseEnter);
            Grid.SetColumn(r, v.pos.X);
            Grid.SetRow(r, v.pos.Y);
            Grid.SetZIndex(r, 330);


            return r;
        }

        /// <summary>
        /// Affiche les Shapes necessaires
        /// </summary>
        private void afficherShapes()
        {
            foreach (Ellipse e in unites)
            {
                mapGrid.Children.Add(e);
                mapGrid.Children.Add((Label)e.Tag);
            }

            foreach (Rectangle r in villes)
            {
                mapGrid.Children.Add(r);
            }
            foreach (Rectangle r in exploitations)
            {
                mapGrid.Children.Add(r);
            }
        }

        /// <summary>
        /// Masque les shapes
        /// </summary>
        private void masquerShapes()
        {
            foreach (Ellipse e in unites)
            {
                mapGrid.Children.Remove(e);
                mapGrid.Children.Remove((Label)e.Tag);
            }
            foreach (Rectangle r in villes)
            {
                mapGrid.Children.Remove(r);
            }
            foreach (Rectangle r in exploitations)
            {
                mapGrid.Children.Remove(r);
            }
        }

        /// <summary>
        /// Cree le rectangle d'une case
        /// </summary>
        /// <param name="c"></param>
        /// <param name="l"></param>
        /// <param name="tile"></param>
        /// <returns></returns>
        private Rectangle creerCase(int c, int l, Case tile)
        {
            var rectangle = new Rectangle();
            rectangle.Width = 50;
            rectangle.Height = 50;
            if (tile is Desert)
                rectangle.Fill = desertvide.Fill;
            if (tile is Montagne)
                rectangle.Fill = montagnevide.Fill;
            if (tile is Plaine)
                rectangle.Fill = plainevide.Fill;
            if (tile is Fruit)
            {
                if (((Ressource)tile).caseRessource is Desert) rectangle.Fill = desertfruit.Fill;
                if (((Ressource)tile).caseRessource is Montagne) rectangle.Fill = montagnefruit.Fill;
                if (((Ressource)tile).caseRessource is Plaine) rectangle.Fill = plainefruit.Fill;
            }
            if (tile is Fer)
            {
                if (((Ressource)tile).caseRessource is Desert) rectangle.Fill = desertfer.Fill;
                if (((Ressource)tile).caseRessource is Montagne) rectangle.Fill = montagnefer.Fill;
                if (((Ressource)tile).caseRessource is Plaine) rectangle.Fill = plainefer.Fill;
            }

            Grid.SetColumn(rectangle, c);
            Grid.SetRow(rectangle, l);
            rectangle.Tag = tile;
            rectangle.MouseEnter += new MouseEventHandler(case_MouseEnter);
            
            return rectangle;
        }

        /// <summary>
        /// Lorsqu'on clique sur une case vide.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void selectionVide(object sender, MouseButtonEventArgs e)
        {
            selectionUnite.Visibility = System.Windows.Visibility.Collapsed;
            selectionUnite.Tag = null;
            selectionVille.Visibility = System.Windows.Visibility.Collapsed;
            selectionVille.Tag = null;
            menu.Height = 151;
            petitMenu.Visibility = System.Windows.Visibility.Visible;
            defaite.Visibility = System.Windows.Visibility.Collapsed;
            majEllipsesDeplacements();
        }

        /// <summary>
        /// Lorsqu'on survole une case
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void case_MouseEnter(object sender, MouseEventArgs e)
        {
            var rectangle = sender as Rectangle;
            int column = Grid.GetColumn(rectangle);
            int row = Grid.GetRow(rectangle);
            Grid.SetColumn(survolCase, column);
            Grid.SetRow(survolCase, row);
            survolCase.Tag = rectangle.Tag;
            survolCase.Visibility = System.Windows.Visibility.Visible;
            survolUnite.Tag = null;
            survolUnite.Visibility = System.Windows.Visibility.Collapsed;
            survolVille.Tag = null;
            survolVille.Visibility = System.Windows.Visibility.Collapsed;
            infoCase.Visibility = System.Windows.Visibility.Visible;
            e.Handled = true;
        }
        
        /// <summary>
        /// Lorsqu'on survolle une unité
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void unite_MouseEnter(object sender, MouseEventArgs e)
        {
            var label = sender as Label;
            var lu = label.Tag as List<Unite>;
            int column = Grid.GetColumn(label);
            int row = Grid.GetRow(label);
            Grid.SetColumn(survolUnite, column);
            Grid.SetRow(survolUnite, row);
            survolUnite.Tag = lu;
            survolUnite.Visibility = System.Windows.Visibility.Visible;
            survolCase.Visibility = System.Windows.Visibility.Collapsed;
            survolVille.Visibility = System.Windows.Visibility.Collapsed;
            meilleureUniteDef.Tag = Etudiant.meilleureUniteDef(lu);
            e.Handled = true;
        }

        /// <summary>
        /// Lorsqu'on clique sur une unité
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void unite_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var survol = sender as Ellipse;
            var lu = survol.Tag as List<Unite>;

            if (lu.First().civilisation == partie.tour.civilisation)
            {
                int column = Grid.GetColumn(survol);
                int row = Grid.GetRow(survol);
                Grid.SetColumn(selectionUnite, column);
                Grid.SetRow(selectionUnite, row);
                selectionUnite.Tag = lu;
                selectionUnite.Visibility = System.Windows.Visibility.Visible;
                selectionVille.Tag = null;
                selectionVille.Visibility = System.Windows.Visibility.Collapsed;
                listUnites.SelectedIndex = 0;
                boutonFonderVille();
                afficherInfosCase(lu.First().pos);
                majEllipsesDeplacements();
            }
            menu.Height = 512;
            petitMenu.Visibility = System.Windows.Visibility.Collapsed;
            
            e.Handled = true;
        }

        /// <summary>
        /// Met à jour le brouillard
        /// </summary>
        private void majBrouillard()
        {

            foreach (Rectangle r in cases)
            {
                r.Opacity = 0.33;
            }

            foreach (Ville v in partie.tour.civilisation.villes)
            {
                foreach (Position p in v.pos.visionSurNCases(3, carte.largeur))
                {
                    cases[p.X, p.Y].Opacity = 0.60;
                }
            }

            foreach (Ville v in partie.tour.civilisation.villes)
            {
                foreach (Position p in v.pos.visionSurNCases(2, carte.largeur))
                {
                    cases[p.X, p.Y].Opacity = 0.80;
                }
            }

            foreach (Ville v in partie.tour.civilisation.villes)
            {
                foreach (Position p in v.pos.visionSurNCases(1, carte.largeur))
                {
                    cases[p.X, p.Y].Opacity = 1;
                }
            }

            foreach (Unite u in partie.tour.civilisation.unites)
            {
                foreach (Position p in u.pos.visionSurNCases(2, carte.largeur))
                {
                    cases[p.X, p.Y].Opacity = 0.66;
                }
            }

            foreach (Unite u in partie.tour.civilisation.unites)
            {
                foreach (Position p in u.pos.visionSurNCases(1, carte.largeur))
                {
                    cases[p.X, p.Y].Opacity = 1;
                }
            }

        }

        /// <summary>
        /// Lorsqu'on survole une ville
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ville_MouseEnter(object sender, MouseEventArgs e)
        {
            var rectangle = sender as Rectangle;
            var ville = rectangle.Tag as Ville;
            int column = Grid.GetColumn(rectangle);
            int row = Grid.GetRow(rectangle);
            Grid.SetColumn(survolVille, column);
            Grid.SetRow(survolVille, row);
            survolVille.Tag = ville;
            survolVille.Visibility = System.Windows.Visibility.Visible;
            survolCase.Tag = null;
            survolCase.Visibility = System.Windows.Visibility.Collapsed;
            survolUnite.Tag = null;
            survolUnite.Visibility = System.Windows.Visibility.Collapsed;
            
            e.Handled = true;
        }

        /// <summary>
        /// Lorsqu'on clique sur une ville
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ville_MouseLeftButtonDown(object sender, MouseEventArgs e)
        {
            var survol = sender as Rectangle;
            var ville = survol.Tag as Ville;

            if (ville.civilisation == partie.tour.civilisation)
            {
                int column = Grid.GetColumn(survol);
                int row = Grid.GetRow(survol);
                Grid.SetColumn(selectionVille, column);
                Grid.SetRow(selectionVille, row);
                selectionVille.Tag = ville;
                selectionVille.Visibility = System.Windows.Visibility.Visible;
                selectionUnite.Tag = null;
                selectionUnite.Visibility = System.Windows.Visibility.Collapsed;
                comboBoxProduction(ville);
                progressionProd.Value = ville.minerai * 100 / ville.enProduction.cout;
                labelProd.Content = ville.enProduction.cout - ville.minerai;
                afficherInfosCase(ville.pos);
            }
            menu.Height = 512;
            petitMenu.Visibility = System.Windows.Visibility.Collapsed;
            e.Handled = true;
        }

        /// <summary>
        /// Met à jour les infos de la case
        /// </summary>
        /// <param name="p"></param>
        void afficherInfosCase(Position p)
        {
            survolCase.Tag = cases[p.X, p.Y].Tag;
            infoCase.Visibility = System.Windows.Visibility.Visible;
        }

        /// <summary>
        /// Gere l'activité du bouton Fonder Ville
        /// </summary>
        void boutonFonderVille()
        {
            var u = listUnites.SelectedValue as Unite;
            if (u == null)
            {
                fonderVille.IsEnabled = false;
            }
            else if (u.estEnseignant())
            {
                if (((Enseignant)u).fondationPossible()) fonderVille.IsEnabled = true;
                else fonderVille.IsEnabled = false;
            }
            else
            {
                fonderVille.IsEnabled = false;
            }
        }

        /// <summary>
        /// Lorqu'on clique sur le bouton Fonder Ville
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void actionFonderVille(object sender, RoutedEventArgs e)
        {
            var u = listUnites.SelectedValue as Enseignant;
            u.creerVille();
            survolUnite.Tag = null;
            survolUnite.Visibility = System.Windows.Visibility.Collapsed;
            
            selectionUnite.Tag = null;
            selectionUnite.Visibility = System.Windows.Visibility.Collapsed;

            
            Grid.SetColumn(selectionVille, Grid.GetColumn(selectionUnite));
            Grid.SetRow(selectionVille, Grid.GetRow(selectionUnite));
            Ville ville = carte.getVille(u.pos);
            selectionVille.Tag = ville;
            selectionVille.Visibility = System.Windows.Visibility.Visible;
            comboBoxProduction(ville);
            progressionProd.Value = ville.minerai * 100 / ville.enProduction.cout;
            labelProd.Content = ville.enProduction.cout - ville.minerai;
            afficherInfosCase(ville.pos);
            majShapes();

        }

        /// <summary>
        /// Selectionne le bon item dans la ComboBox production
        /// </summary>
        /// <param name="v"></param>
        private void comboBoxProduction(Ville v)
        {
            switch (v.enProduction.nom)
            {
                case "Etudiant":
                    production.SelectedItem = productionEtudiant;
                    break;
                case "Enseignant":
                    production.SelectedItem = productionEnseignant;
                    break;
                case "Directeur":
                    production.SelectedItem = productionDirecteur;
                    break;
            }
            productionDirecteur.IsEnabled = !v.civilisation.directeurEnVie;

        }

        /// <summary>
        /// Modifie la production
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void productionSelectionnee(object sender, RoutedEventArgs e)
        {
            var cbi = sender as ListBoxItem;
            var prod = cbi.Content as String;
            var ville = cbi.Tag as Ville;
            ville.modifierProduction(prod);
        }

        /// <summary>
        /// Montre les rectangles des exploitations
        /// </summary>
        private void creerRectanglesExploitations()
        {
            List<Rectangle> lr = new List<Rectangle>();
            foreach (Ville v in partie.tour.civilisation.villes)
            {
                foreach (Position p in v.exploitations)
                {
                    Rectangle r = new Rectangle();
                    r.Style = exploitation.Style;
                    r.Visibility = System.Windows.Visibility.Visible;
                    r.Fill = ColorToSolidColorBrush(v.civilisation.couleurVille);
                    r.Fill.Opacity = 0.5;
                    Grid.SetColumn(r, p.X);
                    Grid.SetRow(r, p.Y);
                    lr.Add(r);
                }
            }
            exploitations = lr;
        }

        /// <summary>
        /// Affiche les Ellipses des deplacements possibles
        /// </summary>
        private void creerEllipsesDeplacements()
        {
            List<Ellipse> le = new List<Ellipse>();
            var unite = listUnites.SelectedValue as Unite;
            if (unite == null || unite.mvt < 1)
            {
                deplacements.Clear();
                return;
            }
            List<Position> lp = unite.pos.visionSurNCases(unite.mvt, carte.largeur);

            foreach (Position p in lp)
            {
                Ellipse e = new Ellipse();
                e.Style = deplacement.Style;
                e.Visibility = System.Windows.Visibility.Visible;
                e.MouseLeftButtonDown += new MouseButtonEventHandler(deplacerUniteClick);
                e.Tag = p;
                Grid.SetColumn(e, p.X);
                Grid.SetRow(e, p.Y);
                le.Add(e);
            }

            deplacements = le;

        }

        /// <summary>
        /// Met a jour les ellipses des deplacements possibles
        /// </summary>
        private void majEllipsesDeplacements()
        {
            foreach (Ellipse e in deplacements)
            {
                mapGrid.Children.Remove(e);
            }
            creerEllipsesDeplacements();
            foreach (Ellipse e in deplacements)
            {
                mapGrid.Children.Add(e);
            }
        }

        /// <summary>
        /// Lors d'un clique à un endroit quelconque de la fenetre
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            survolVille.Tag = null;
            survolVille.Visibility = System.Windows.Visibility.Collapsed;
            survolCase.Tag = null;
            survolCase.Visibility = System.Windows.Visibility.Collapsed;
            survolUnite.Tag = null;
            survolUnite.Visibility = System.Windows.Visibility.Collapsed;
        }
         
        /// <summary>
        /// Gere le bouton tour suivant
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void boutonTourSuivant(object sender, RoutedEventArgs e)
        {
            tourSuivant();
        }

        /// <summary>
        /// Actions lors du passage au tour suivant
        /// </summary>
        private void tourSuivant()
        {
            partie.joueurSuivant();
            majShapes();
            survolCase.Tag = null;
            survolCase.Visibility = System.Windows.Visibility.Collapsed;
            survolUnite.Tag = null;
            survolUnite.Visibility = System.Windows.Visibility.Collapsed;
            survolVille.Tag = null;
            survolVille.Visibility = System.Windows.Visibility.Collapsed;
            selectionVille.Tag = null;
            selectionVille.Visibility = System.Windows.Visibility.Collapsed;
            selectionUnite.Tag = null;
            selectionUnite.Visibility = System.Windows.Visibility.Collapsed;
            menu.Height = 151;
            petitMenu.Visibility = System.Windows.Visibility.Visible;
            majEllipsesDeplacements();
            majBrouillard();
            _root.Tag = partie.tour;
        }

        /// <summary>
        /// Converti une Color en SolidColorBrush
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        private static SolidColorBrush ColorToSolidColorBrush(System.Drawing.Color c)
        {
            return new SolidColorBrush(System.Windows.Media.Color.FromArgb(c.A, c.R, c.G, c.B));
        }

        /// <summary>
        /// Met à jour l'unite selectionnée
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void majSelectedValue(object sender, SelectionChangedEventArgs e)
        {
            majEllipsesDeplacements();
            boutonFonderVille();
        }

        /// <summary>
        /// Sauvegarde la partie en cours
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Sauvegarder(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.SaveFileDialog boiteSauvegarde = new System.Windows.Forms.SaveFileDialog();
            boiteSauvegarde.Filter = "Fichier bin(*.bin)|*.bin";
            if (boiteSauvegarde.ShowDialog() == System.Windows.Forms.DialogResult.OK) partie.Sauvegarder(boiteSauvegarde.FileName);
        }

        /// <summary>
        /// Deplace une unite par le clique
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void deplacerUniteClick(object sender, MouseButtonEventArgs e)
        {
            var ellipse = sender as Ellipse;
            var pos = ellipse.Tag as Position;
            var u = (Unite)listUnites.SelectedValue;
            if (u.deplacer(pos))
            {
                if (u.vie == 0) selectionUnite.Visibility = System.Windows.Visibility.Collapsed;
                majShapes();
                survolUnite.Visibility = System.Windows.Visibility.Collapsed;
                mvt.GetBindingExpression(Label.ContentProperty).UpdateTarget();
                vie.GetBindingExpression(Label.ContentProperty).UpdateTarget();
                majSelectionUnite(u);
                majEllipsesDeplacements();
                majBrouillard();
                boutonFonderVille();
                finDePartie();
            }
            e.Handled = true;
        }


        /// <summary>
        /// Dernier bouton sur lequel un perdant cliquera.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void finDuJoueur(object sender, RoutedEventArgs e)
        {
            selectionUnite.Visibility = System.Windows.Visibility.Collapsed;
            selectionUnite.Tag = null;
            selectionVille.Visibility = System.Windows.Visibility.Collapsed;
            selectionVille.Tag = null;
            menu.Height = 151;
            petitMenu.Visibility = System.Windows.Visibility.Visible;
            defaite.Visibility = System.Windows.Visibility.Collapsed;
            majEllipsesDeplacements();
        }
    }
}
